﻿using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
using CommonTool;

/// <summary>
/// 客户端 服务器类
/// </summary>
namespace Tool
{
    public class Communicate
    {
        private Socket mySocket;
        private TcpListener mServer;
        private IPEndPoint myIPEndPoint;
        private byte[] tempByte = new byte[1024];
        private string receiveMess;
        private NetPara _netPara;
        private bool sendEnable = false;
        private bool _isSendingCheck = false;


        /// <summary>
        /// 网络连接参数
        /// </summary>
        public NetPara CommunicatePara
        {
            get { return this._netPara; }
        }
        /// <summary>
        /// 网络连接的名称
        /// </summary>
        public string NetName
        {
            set;
            get;
        }

        public bool conResult = false;

        public delegate void ConnectResultEventHandler(object sender, ResultEventArgs e);

        public delegate void MessageReceivedEventHandler(object sender, MessageEventArgs e);
        /// <summary>
        /// 当接受到数据信息时发生
        /// </summary>
        public event MessageReceivedEventHandler MessageReceived;//接受到数据事件
        /// <summary>
        /// 连接状态发生改变时发生
        /// </summary>
        public event ConnectResultEventHandler ConnectedResult;//连接成功事件

        private System.Threading.Thread checkConnectThread;

        System.Threading.Thread connectThread, receiveThread;

        public Communicate()
        {

        }

        public Communicate(string commName, string ip, int port)
        {

            this.NetName = commName;
            this._netPara = new NetPara(commName);
            this._netPara.SetPara(ip, port, NetBehavior.Client);
            this.myIPEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
            mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        }

        public void IniClientorSever(bool isSendingCheck = false)
        {
           

            this._isSendingCheck = isSendingCheck;
            if (connectThread != null)
            {
                connectThread = null;
            }
            if (receiveThread != null)
            {
                receiveThread = null;
            }
            connectThread = new System.Threading.Thread(Connect);
            connectThread.IsBackground = true;
            connectThread.Start();

            receiveThread = new System.Threading.Thread(ReceiveMessage);
            receiveThread.IsBackground = true;
            receiveThread.Start();
            receiveMess = "";
        }

        public class ResultEventArgs : EventArgs
        {
            /// <summary>
            /// 网络是否成功连接
            /// </summary>
            public bool isConnected
            {
                private set;
                get;
            }
            public ResultEventArgs(bool conResult)
            {
                this.isConnected = conResult;
            }
        }

        public class MessageEventArgs : EventArgs
        {
            /// <summary>
            /// 接受到的网络数据
            /// </summary>
            public string Message
            {
                private set;
                get;
            }
            /// <summary>
            /// 字节长度
            /// </summary>
            public int byteLength
            {
                get;
                set;
            }

            public MessageEventArgs(string message)
            {
                this.Message = message;
            }
        }
        /// <summary>
        /// 网络连接的IP地址
        /// </summary>
        public string IpAddress { get; set; }//定义属性--IP地址

        /// <summary>
        /// 网络连接的端口号
        /// </summary>
        public int Port//定义属性--端口号
        {
            set
            {
                this.myIPEndPoint.Port = value;
            }
            get
            {
                return myIPEndPoint.Port;
            }

        }
        /// <summary>
        /// 尝试连接服务器或者客户端
        /// </summary>
        public void Connect()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(500);
                CloseSocket();
                this.myIPEndPoint = new IPEndPoint(IPAddress.Parse(CommunicatePara.Ip), CommunicatePara.Port);
                if (CommunicatePara.ClientOrServer == NetBehavior.Client)
                {
                    try
                    {
                        mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        mySocket.Connect(myIPEndPoint);
                        conResult = true;
                        checkConnectThread = new System.Threading.Thread(CheckConnect);
                        checkConnectThread.IsBackground = true;
                        checkConnectThread.Start();
                        ResultEventArgs e = new ResultEventArgs(conResult);
                        ResultToDo(e);
                        break;
                    }
                    catch
                    {
                        conResult = false;
                    }
                }
                else
                {

                    try
                    {

                        if (mServer == null)
                        {
                            mServer = new TcpListener(myIPEndPoint);
                        }
                        mServer.Start();
                        mySocket = mServer.AcceptSocket();
                        conResult = true;
                        ResultToDo(new ResultEventArgs(conResult));
                        if (checkConnectThread != null)
                        {
                            checkConnectThread = null;
                        }
                        checkConnectThread = new System.Threading.Thread(CheckConnect);
                        checkConnectThread.IsBackground = true;
                        checkConnectThread.Start();
                        break;
                    }
                    catch
                    {
                        mServer = null;
                        mServer = new TcpListener(myIPEndPoint);
                        conResult = false;
                    }
                }

            }

        }
        /// <summary>
        /// 关闭Socket连接
        /// </summary>
        public void CloseSocket()
        {
            if (this.mySocket != null)
            {
                if (this.mySocket.Connected)
                {
                    this.mySocket.Shutdown(SocketShutdown.Both);
                }
                this.mySocket.Close(100);
                this.mySocket = null;
            }


            try
            {
                mServer.Stop();
            }
            catch
            {

            }

        }

        protected virtual void ResultToDo(ResultEventArgs e)
        {
            if (ConnectedResult != null)
            {
                ConnectedResult(this, e);
            }
        }
        /// <summary>
        /// 检测网络连接是否断开
        /// </summary>
        private void CheckConnect()
        {
            while (true)
            {
                System.Threading.Thread.Sleep(30);

                if (mySocket != null && !sendEnable)
                {
                    bool isErr = false;
                    if (_isSendingCheck)
                    {
                        try
                        {
                            byte[] by = Encoding.Default.GetBytes(" ");
                            mySocket.Send(by);
                        }
                        catch
                        {
                            isErr = true;
                        }
                    }
                    else
                    {
                        bool _res = mySocket.Poll(0, SelectMode.SelectRead);
                        isErr = _res;
                    }

                    if (isErr)
                    {
                        conResult = false;
                        ResultEventArgs e = new ResultEventArgs(conResult);
                        ResultToDo(e);
                        mySocket = null;

                        if (connectThread != null)
                        {
                            connectThread.Abort();
                        }
                        if (receiveThread != null)
                        {
                            receiveThread.Abort();
                        }
                        try
                        {
                            connectThread = new System.Threading.Thread(Connect);
                            connectThread.IsBackground = true;
                            connectThread.Start();
                        }
                        catch
                        {
                            MessageBox.Show(" ");
                        }

                        break;
                    }
                }

            }
        }

        /// <summary>
        /// 循环接受客户端或者服务器发送的信息
        /// </summary>
        public void ReceiveMessage()//接收数据
        {
            while (true)
            {
                System.Threading.Thread.Sleep(3);

                if (mySocket != null)
                {
                    if (mySocket.Connected)
                    {
                        int numReceive = 0;
                        try
                        {
                            numReceive = mySocket.Receive(tempByte, SocketFlags.None);
                        }
                        catch
                        {

                        }
                        if (numReceive > 0)
                        {
                            receiveMess = Encoding.ASCII.GetString(tempByte, 0, numReceive);
                            MessageEventArgs e = new MessageEventArgs(receiveMess);
                            if (MessageReceived != null)
                            {
                                System.Threading.Tasks.Task.Factory.StartNew(() => MessageReceived(this, e));
                            }
                        }
                    }
                }

            }
        }

        /// <summary>
        /// 向服务器或者客户端发送信息
        /// </summary>
        /// <param name="text">需要发送的信息内容</param>
        public void SendMessage(string text)//发送数据
        {
            if (mySocket != null)
            {
                sendEnable = true;
                //System.Threading.Thread.Sleep(50);
                byte[] buffer = Encoding.Default.GetBytes(text);
                try
                {
                    mySocket.Send(buffer, buffer.Length, SocketFlags.None);
                }
                catch (Exception ex)
                {
                    LogView.GetInstance().ShowLogSave(LogView.LogType.Error, ex.Message);//保存Log
                    MessageBox.Show(ex.Message);
                }
                sendEnable = false;
            }
        }
        /// <summary>
        /// 向服务器或者客户端发送信息
        /// </summary>
        /// <param name="text">需要发送的信息内容</param>
        /// <param name="isHex">是否以16进制发送</param>
        public bool SendMessage(string text, bool isHex)
        {
            bool result = false;
            if (mySocket != null)
            {
                //System.Threading.Thread.Sleep(30);
                byte[] buffer;
                if (!isHex)
                {
                    buffer = Encoding.Default.GetBytes(text);
                }
                else
                {
                    text = text.Replace(" ", "");
                    if ((text.Length % 2) != 0)
                    {
                        text += " ";
                    }
                    buffer = new byte[text.Length / 2];
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] = Convert.ToByte(text.Substring(i * 2, 2).Trim(), 16);
                    }
                }
                try
                {
                    mySocket.Send(buffer, buffer.Length, SocketFlags.None);
                    result = true;
                }
                catch (Exception ex)
                {
                    LogView.GetInstance().ShowLogSave(LogView.LogType.Error, ex.Message);//保存Log
                    MessageBox.Show(ex.Message);
                    result = false;
                    System.Threading.Thread.Sleep(30);
                    conResult = false;

                    ResultEventArgs e = new ResultEventArgs(conResult);
                    ResultToDo(e);
                }
            }
            else
            {
                result = false;
            }
            return result;
        }
    }
    [Serializable]
    public enum NetBehavior
    {
        /// <summary>
        /// 服务器
        /// </summary>
        Server = 1,//服务器
        /// <summary>
        /// 客户端
        /// </summary>
        Client = 2,//客户端
    }

    [Serializable]
    public class NetPara
    {
        private string _ip = "192.168.0.100";
        private int _port = 8080;
        private NetBehavior _behavior = NetBehavior.Server;
        private string _netParaName = System.Windows.Forms.Application.StartupPath + "\\dn.np";
        /// <summary>
        /// IP地址
        /// </summary>
        public string Ip
        {
            get { return _ip; }
            set { _ip = value; }
        }
        /// <summary>\
        /// 端口号
        /// </summary>
        public int Port
        {
            get { return _port; }
            set { _port = value; }
        }
        /// <summary>
        /// 客户端或服务器
        /// </summary>
        public NetBehavior ClientOrServer
        {
            set
            {
                this._behavior = value;
            }
            get
            {
                return this._behavior;
            }
        }
        /// <summary>
        /// 网络参数的名称
        /// </summary>
        public string NetParaName
        {
            private set
            {
                this._netParaName = value;
            }
            get
            {
                return this._netParaName;
            }
        }
        /// <summary>
        /// 设置网络参数
        /// </summary>
        /// <param name="ip">ip地址</param>
        /// <param name="port">端口号</param>
        /// <param name="ClientorServer">服务器或者客户端</param>
        public void SetPara(string ip, int port, NetBehavior ClientorServer)
        {
            try
            {
                this._ip = ip;
                this._port = port;
                this._behavior = ClientorServer;
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("设置网络参数时出现以下错误\r\n" + ex.Message, "设置网络参数时...");
            }
        }
        /// <summary>
        /// 保存所有网络参数
        /// </summary>
        public void SavePara()
        {
            try
            {
                BinaryFormatter bf = new BinaryFormatter();
                FileStream fs = new FileStream(_netParaName, FileMode.OpenOrCreate, FileAccess.Write);
                bf.Serialize(fs, this);
                fs.Flush();
                fs.Close();
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show("网络数据保存失敗！\r\n " + ex.Message, "参数保存...");
            }
        }
        /// <summary>
        /// 初始化参数
        /// </summary>
        public void IniPara()
        {
            if (System.IO.File.Exists(_netParaName))
            {
                try
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    FileStream fs = new FileStream(_netParaName, FileMode.Open, FileAccess.Read);
                    NetPara netPara = (NetPara)bf.Deserialize(fs);
                    fs.Flush();
                    fs.Close();
                    this.Ip = netPara.Ip;
                    this.Port = netPara.Port;
                    this.ClientOrServer = netPara.ClientOrServer;
                    //this.ClientOrServer = NetBehavior.Client;
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show("初始化网络数据失败！\r\n" + ex.Message, "初始化参数...");
                }
            }
        }
        /// <summary>
        /// 初始化指定名称的网络参数
        /// </summary>
        /// <param name="paraName">网络名称</param>
        public NetPara(string paraName)
        {
            this._netParaName = string.Format("{0}\\{1}.np", System.Windows.Forms.Application.StartupPath, paraName);
            IniPara();
        }

    }




}
